package com.flag.liutao.modules.auth.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.flag.liutao.common.domain.LocalUser;
import com.flag.liutao.common.handler.MyException;
import com.flag.liutao.common.utils.JwtUtil;
import com.flag.liutao.common.utils.RedisUtil;
import com.flag.liutao.common.enums.AuthEnum;
import com.flag.liutao.modules.auth.service.AuthService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
@Slf4j
public class AuthServiceImpl implements  AuthService {

    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private RedisUtil redisUtil;



    /**
     * 管理员登录方法
     * @param userName
     * @param password
     * @param code
     * @return
     */
    @Override
    public Map<String, String> adminLogin(String userName, String password, String code) {
        String verify = getCode();
        if (!code.equalsIgnoreCase(verify)) {
            throw new MyException("验证码错误");
        }
        //使用springSecurity 自带的认证类对账号密码进行认证，返回一个authenticate类
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userName,password);
        Authentication authenticate = authenticationManager.authenticate(authenticationToken);
        if(ObjectUtil.isNull(authenticate)){
            throw new MyException("用户名或密码错误");
        }
        //获取JWT
        LocalUser localUser = (LocalUser) authenticate.getPrincipal();
        String token = JwtUtil.createJWT(localUser.getUser().getId().toString());
        //将用户信息存入JWT中
        String userInfo = JSONObject.toJSONString(localUser);

        List<String> list = authenticate.getAuthorities().stream().map(auth->{
            return ((GrantedAuthority) auth).getAuthority();
        }).collect(Collectors.toList());

        if(!list.contains(AuthEnum.ADMIN_LOIN.getValue())){
            throw new RuntimeException("没有"+AuthEnum.ADMIN_LOIN.getDesc()+"权限");
        }
        redisUtil.setCacheObject(AuthEnum.ADMIN_TOKEN.getValue()+localUser.getUser().getId()+token,userInfo,1,TimeUnit.DAYS);
        //返回结果集
        Map<String,String> map = new HashMap<>();
        map.put(AuthEnum.TOKEN_NAME.getValue(),token);
        return map;
    }

    /**
     * 普通用户登录的方法
     * @param userName
     * @param password
     * @param code
     * @return
     */
    @Override
    public Map<String, String> login(String userName, String password, String code) {
        if (!code.equalsIgnoreCase(getCode())) {
            throw new MyException("验证码错误");
        }
        //使用springSecurity自带的认证类对账号密码进行认证，返回一个authenticate类
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userName,password);
        Authentication authenticate = authenticationManager.authenticate(authenticationToken);

        if(ObjectUtil.isNull(authenticate)){
            throw new MyException("用户名或密码错误");
        }

        LocalUser localUser = (LocalUser) authenticate.getPrincipal();
        String token = JwtUtil.createJWT(localUser.getUser().getId().toString());


        List<String> list = authenticate.getAuthorities().stream().map(auth->{
            return ((GrantedAuthority) auth).getAuthority();
        }).collect(Collectors.toList());

        if(!list.contains(AuthEnum.API_LOGIN.getValue())){
            throw new MyException("没有"+AuthEnum.API_LOGIN.getDesc()+"权限");
        }

        String userInfo = JSONObject.toJSONString(localUser);

        redisUtil.setCacheObject(AuthEnum.API_TOEKN.getValue()+localUser.getUser().getId()+token,userInfo);

        Map<String,String> map = new HashMap<>();
        map.put("Authorization",token);
        return map;
    }

    /**
     * 获取验证码
     * @return
     */
    @Override
    public String getCode() {
        return redisUtil.getCacheObject(AuthEnum.LOGIN_CODE.getValue());
    }

    /**
     * 设置验证码到redis中
     * @param code
     * @param minutes
     */
    @Override
    public void setCode(String code, int minutes) {
        redisUtil.setCacheObject(AuthEnum.LOGIN_CODE.getValue(),code,minutes, TimeUnit.MINUTES);
    }

    /**
     * 删除验证码
     */
    @Override
    public void remoeCode() {
        redisUtil.deleteObject(AuthEnum.LOGIN_CODE.getValue());
    }

    /**
     * 退出登陆的方法
     * @param type
     * @param id
     * @param token
     */
    @Override
    public void logout(String type, Long id, String token) {
        redisUtil.deleteObject(type+id+token);
    }

}
